﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Diagnostics;

namespace EvoBoost.Core
{
	[Serializable]
	public class Forest<T>
	{
		private readonly double shrinkage;

		private readonly List<Tree<T>> trees;
		
		internal Forest(Tree<T> baseTree, IEnumerable<Tree<T>> trees, double shrinkage)
		{
			Debug.Assert(trees != null);
			Debug.Assert(shrinkage > 0 && shrinkage <= 1);
			Debug.Assert(baseTree != null);
			
			this.trees = new List<Tree<T>>(trees);
			this.shrinkage = shrinkage;
			this.BaseTree = baseTree;
		}

		public Tree<T> BaseTree { get; private set; }

		public ReadOnlyCollection<Tree<T>> Trees
		{
			get { return this.trees.AsReadOnly(); }
		}

		public Forest<T> GetSubForest(int howMuchTrees)
		{
			return new Forest<T>(this.BaseTree, this.trees.Take(howMuchTrees), this.shrinkage);
		}

		public double CalculateOutcome(T properties)
		{
			double outcome = 0;
			foreach (Tree<T> tree in trees)
				outcome += tree.CalculateOutcome(properties);

			return (outcome * this.shrinkage) + this.BaseTree.CalculateOutcome(properties);
		}
	}
}
